package cn.luowb.checkchat.task;

import cn.luowb.checkchat.common.util.RedisKeyUtil;
import cn.luowb.checkchat.dao.mapper.LikeMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;

@Component
@Slf4j
@RequiredArgsConstructor
public class LikeSyncTask {

    private final LikeMapper likeMapper;
    private final StringRedisTemplate stringRedisTemplate;
    private final RedisKeyUtil redisKeyUtil;

    // 定义类型常量
    private static final int TYPE_POST = 0;
    private static final int TYPE_COMMENT = 1;

    /**
     * 每天凌晨3点执行一次点赞数据同步
     */
    @Scheduled(cron = "0 0 3 * * ?")
//    @Scheduled(cron = "0 * * * * ?") // 测试用
    public void syncLikeData() {
        log.info("开始同步点赞数据到Redis");

        try {
            // 先清理所有旧的点赞数据
            cleanupAllLikeSets();

            // 同步帖子点赞数据
            syncLikeDataByType(TYPE_POST);

            // 同步评论点赞数据
            syncLikeDataByType(TYPE_COMMENT);

            log.info("点赞数据同步完成");
        } catch (Exception e) {
            log.error("同步点赞数据到Redis失败", e);
        }
    }

    /**
     * 按类型同步点赞数据
     *
     * @param type 类型：0-帖子点赞 1-评论点赞
     */
    private void syncLikeDataByType(int type) {
        // 查询数据库中的所有点赞数据（按类型分组）
        List<Map<String, Object>> allLikes = likeMapper.selectLikeDataGroupByObject(type);

        if (CollectionUtils.isEmpty(allLikes)) {
            log.info("类型{}没有点赞数据需要同步", type);
            return;
        }


        // 遍历每个对象的点赞数据
        for (Map<String, Object> data : allLikes) {
            Long objId = (Long) data.get("obj_id");
            Long likeCount = (Long) data.get("like_count");

            // 查询该对象的所有点赞用户ID
            List<Long> userIds = likeMapper.selectUserIdsByObjIdAndType(objId, type);

            // 构建Redis Key
            String setKey = redisKeyUtil.buildLikeSetKey(type, objId);

            // 删除旧的Redis数据（如果有）
            stringRedisTemplate.delete(setKey);

            // 将用户ID集合添加到Redis Set中
            if (!CollectionUtils.isEmpty(userIds)) {
                stringRedisTemplate.opsForSet().add(setKey,
                        userIds.stream()
                                .map(String::valueOf)
                                .distinct()
                                .toArray(String[]::new)
                );
            }
            log.debug("同步类型{}对象{}的点赞数据，共{}个点赞", type, objId, userIds.size());
        }
        log.info("类型{}的点赞数据同步完成，共{}个对象", type, allLikes.size());
    }

    private void cleanupAllLikeSets() {
        log.info("开始清理所有点赞Set数据");

        try {
            // 构建点赞Set的key模式
            String pattern = redisKeyUtil.getProjectPrefix() + ":like:set:*";

            // SCAN 实现
            Set<String> keys = redisKeyUtil.scanKeys(pattern);

            if (CollectionUtils.isEmpty(keys)) {
                log.info("没有找到需要删除的点赞Set");
                return;
            }
            stringRedisTemplate.delete(keys);
            log.info("成功删除 {} 个点赞Set", keys.size());

            log.info("点赞Set数据清理完成");
        } catch (Exception e) {
            log.error("清理点赞Set数据失败", e);
        }
    }
}